﻿using System;
using System.Threading;
using System.Windows.Forms;
using SG.Sys.Console.CommandProcessing;
using SG.Sys.Console.Process;
using SG.Sys.Console.Tab;

namespace SG.Sys.Console.View
{
    public partial class ConsolePane : UserControl
    {
        public event EventHandler<TitleChangedEventArgs> OnTitleChanged;
        public event EventHandler OnClose;

        public IProcessWrapper Wrapper { get; private set; }
        public ICommandHistory History { get; private set; }

        private bool IsControlKeyHold { get; set; }

        public ConsolePane()
        {
            InitializeComponent();
            textInput.MouseWheel += textInput_MouseWheel;
        }

        void textInput_MouseWheel(object sender, MouseEventArgs e)
        {
            ProcessKeyEvent(e.Delta < 0 ? new KeyEventArgs(Keys.Down) : new KeyEventArgs(Keys.Up));
        }

        public void Initialize(IProcessWrapper wrapper)
        {
            Wrapper = wrapper;
            Wrapper.OnOutput += Wrapper_OnOutput;
            Wrapper.Start();
            History = new CommandHistory(Wrapper.ParseCommand);
        }

        void Wrapper_OnOutput(object sender, LineOutputEvent e)
        {
            if (IsDisposed || textOutput == null) return; 

            Action<LineOutputEvent> printer = PrintToTextBox;

            var hasHandle = false;
            for (var i = 0; i < 1000; i++)
            {
                if (!IsHandleCreated)
                    Thread.Sleep(1);
                else
                {
                    hasHandle = true;
                    break;
                }
            }

            if (hasHandle)
                Invoke(printer, e);
        }

        private void FireTitleChange(TitleChangedEventArgs titleChangedEventArgs)
        {
            var copy = OnTitleChanged;
            if (copy != null)
                copy(this, titleChangedEventArgs);
        }

        public void SendClose()
        {
            Wrapper.OnOutput -= Wrapper_OnOutput;
            Wrapper.SendClose();

            var copy = OnClose;
            if (copy != null)
                copy(this, new EventArgs());
        }

        private void textInput_KeyDown(object sender, KeyEventArgs e)
        {
            ProcessKeyEvent(e);
        }

        private void textInput_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\t')
                e.Handled = true;
        }

        private void textOutput_KeyDown(object sender, KeyEventArgs e)
        {
            ProcessKeyEvent(e);
            FocusInput();
        }

        public void FocusInput()
        {
            
            Action focus = () =>
                               {
                                   ActiveControl = textInput;
                                   textInput.Focus();
                               };
            Invoke(focus);
        }

        private void ConsolePane_Load(object sender, EventArgs e)
        {
            ActiveControl = textInput;
        }

        private void textOutput_KeyPress(object sender, KeyPressEventArgs e)
        {
            var @char = e.KeyChar;
            if (!char.IsControl(@char))
                AppendText(textInput, ""+e.KeyChar, new FormatOptions{PrettyPrint = true});
        }

        private void textInput_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            ProcessLink(e.LinkText);
        }

        private void textOutput_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            ProcessLink(e.LinkText);
        }

        private void textOutput_KeyUp(object sender, KeyEventArgs e)
        {
            IsControlKeyHold = false;
        }

        private void textInput_KeyUp(object sender, KeyEventArgs e)
        {
            IsControlKeyHold = false;
        }
    }
}
